package com.whity.towerdefense.model;

import java.io.IOException;
import java.util.Vector;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.graphics.Point;
import android.util.Log;

public class SpawnPoint implements I_Tickable
{
	private enum SpawnPointMode {CYCLE, RANDOM};
	// =============================================================
	// Private attributs :
	
	private static final String		TAG = "com.djm.test03.model";
	
	private final Vector<Point>		m_Points;
	private final int				m_StartTime;	// Time, in Ms, after the start of the wave, at which the first unit will spawn.
	private final int				m_Rate;			// Time in Ms between each unit spawned.
	private final int				m_Repetition;	// Number of time we will spawn each unit of the sequence
	private final Vector<String>	m_UnitTypeIds;
	private final SpawnPointMode	m_Mode;
	
	private int						m_TimeElapsed; // number of Ms since this SpawnPoint has been activated
	private int						m_TimeBeforeNextUnit;
	private int						m_NextUnit;
	private int						m_NextPoints;
	private int						m_RemainRepetition;
	private boolean					m_Active; 		// True if the spawn will spawn another unit in the futur
	
	// =============================================================
	// Public functions
	
	public SpawnPoint(XmlPullParser p_XmlParser) throws ParsingException, XmlPullParserException, IOException
	{
		// TODO : Read the mode from the xml
		m_Mode = SpawnPointMode.CYCLE;
		m_TimeElapsed = 0;
		m_NextUnit = 0;
		m_NextPoints = 0;
		m_Active = true;
				
		if(!p_XmlParser.getName().equals("SpawnPoint"))
    	{
			Log.w(TAG, "Can't initialise a SpawnPoint with an Xml item : " + p_XmlParser.getName());
			throw(new ParsingException("Can't initialise a SpawnPoint with an Xml item : " + p_XmlParser.getName()));
		}
		
		m_StartTime = (int)(Float.parseFloat(p_XmlParser.getAttributeValue(null, "StartTime"))*1000);
		m_Rate = (int)(1000.0f / Float.parseFloat(p_XmlParser.getAttributeValue(null, "Rate")));
		m_Repetition = Integer.parseInt(p_XmlParser.getAttributeValue(null, "Repetition"));
		m_RemainRepetition = m_Repetition;
		m_UnitTypeIds = new Vector<String>();
		m_Points = new Vector<Point>();
		String ptStr = p_XmlParser.getAttributeValue(null, "Points");
		String[] ptsStr = ptStr.split(";");
		m_TimeBeforeNextUnit = 0;
		for(int i = 0 ; i < ptsStr.length ; i++)
		{
			String pointStr = ptsStr[i].replaceAll("[()]", "");
			String[] indiceStr = pointStr.split(",");
			m_Points.add(new Point(Integer.parseInt(indiceStr[0]), Integer.parseInt(indiceStr[1])));
		}
		
		// Load unit types
		int eventType = p_XmlParser.getEventType();
		while(!(eventType == XmlPullParser.END_TAG && p_XmlParser.getName().equals("SpawnPoint")))
		{
			if(eventType == XmlPullParser.START_TAG)
            {
				if(p_XmlParser.getName().equals("Unit"))
		    	{
					m_UnitTypeIds.add(UnitFactory.CreateNewType(p_XmlParser));
		    	}
            }
			eventType = p_XmlParser.next();
		}
		
		// TODO Consistency check
	}

	public int GetStartTime()
	{
		return m_StartTime;
	}
	
	public boolean GameTick(int p_Ms)
	{
		m_TimeElapsed += p_Ms;
		m_TimeBeforeNextUnit -= p_Ms;
		
		if(m_TimeBeforeNextUnit <= 0)
		{
			// It's time for a new unit !
			if(m_NextUnit < m_UnitTypeIds.size())
			{
				// Release the current unit !
				m_TimeBeforeNextUnit = m_Rate;
				Unit newUnit = UnitFactory.CreateUnit(m_UnitTypeIds.get(m_NextUnit), m_Points.get(m_NextPoints).x + 0.5f, m_Points.get(m_NextPoints).y + 0.5f);
				GameModel.LEVEL.AddUnit(newUnit);
			}
			else
			{
				// Start over with the first unit of the list if the number of repetition is not over.
				m_RemainRepetition--;
				if(m_RemainRepetition <= 0)
				{
					m_Active = false;
					return false;
				}
				else
				{
					m_NextUnit = 0;
					m_TimeBeforeNextUnit = m_Rate;
					Unit newUnit = UnitFactory.CreateUnit(m_UnitTypeIds.get(m_NextUnit), m_Points.get(m_NextPoints).x + 0.5f, m_Points.get(m_NextPoints).y + 0.5f);
					GameModel.LEVEL.AddUnit(newUnit);
				}
			}
			m_NextUnit++;
			m_NextPoints++;
			if(m_NextPoints >= m_Points.size())
			{
				m_NextPoints = 0;
			}
		}
		return true;
	}
	
	public boolean IsActif()
	{
		return m_Active;
	}
	
	public void RecalculatePathfinding()
	{
		
	}
	
	// =============================================================
}
